﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Caching;

namespace kysec.CR.Cache
{
    public class CacheManage
    {
        protected static volatile System.Web.Caching.Cache webCache =
            System.Web.HttpRuntime.Cache;

        private static object syncObj = new object();

        protected System.Web.Caching.Cache WebCache
        {
            get
            {
                if (webCache != null)
                { return webCache; }
                return null;
            }
        }

        public sealed class DefaultStrategy
        {
            private static DefaultStrategy instance = null;
            public static DefaultStrategy GetEntity()
            {
                if (instance == null)
                {
                    lock (syncObj)
                    {
                        if (instance == null)
                        {
                            instance = new DefaultStrategy();
                        }
                    }
                }
                return instance;
            }
            public void AddObjectWithNoExpired(string objId, object o, Action<string, object> RemoveCallBack, Action<string, object> UnderusedCallBack)
            {
                if (webCache != null)
                {
                    webCache.Insert(objId,
                        o,
                        null,
                        System.Web.Caching.Cache.NoAbsoluteExpiration,
                        System.Web.Caching.Cache.NoSlidingExpiration,
                        CacheItemPriority.BelowNormal,
                        (key, value, reason) =>
                        {
                            switch (reason)
                            {
                                case CacheItemRemovedReason.Removed:
                                    if (RemoveCallBack != null)
                                    {
                                        RemoveCallBack.Invoke(key, value);
                                    }
                                    break;
                                case CacheItemRemovedReason.Underused:
                                    if (UnderusedCallBack != null)
                                    {
                                        UnderusedCallBack.Invoke(key, value);
                                    }
                                    break;
                            }
                        });
                }
            }
            /// <summary>
            /// 缓存数据，使用绝对过期时间
            /// </summary>
            /// <param name="objId">键</param>
            /// <param name="o">值</param>
            /// <param name="absoluteTime">缓存时间（单位：毫秒）</param>
            /// <param name="priority">缓存优先级</param>
            public void AddObjectWithAbsoluteTime(string objId, object o, int absoluteTime, System.Web.Caching.CacheItemPriority priority)
            {
                if (absoluteTime > 0 && webCache != null)
                {
                    if (!String.IsNullOrEmpty(objId) && o != null)
                    {
                        webCache.Insert(objId
                            , o
                            , null
                            , DateTime.Now.AddMilliseconds(absoluteTime)
                            , System.Web.Caching.Cache.NoSlidingExpiration
                            , priority
                            , null);
                    }
                }
            }
            public void AddObjectWithAbsoluteTime(string objId, object o, int absoluteTime, System.Web.Caching.CacheItemPriority priority, CacheItemRemovedCallback target)
            {
                if (absoluteTime > 0 && webCache != null)
                {
                    if (!String.IsNullOrEmpty(objId) && o != null)
                    {
                        webCache.Insert(objId
                            , o
                            , null
                            , DateTime.Now.AddMilliseconds(absoluteTime)
                            , System.Web.Caching.Cache.NoSlidingExpiration
                            , priority
                            , target);
                    }
                }
            }
            public void AddObjectWithSlidingTime(string objId, object o, int slidingTime, System.Web.Caching.CacheItemPriority priority)
            {
                if (slidingTime > 0 && webCache != null)
                {
                    if (!String.IsNullOrEmpty(objId) && o != null)
                    {
                        webCache.Insert(objId
                            , o
                            , null
                            , DateTime.MaxValue
                            , TimeSpan.FromMilliseconds(slidingTime)
                            , priority
                            , null);
                    }
                }
            }
            public void AddObjectWithSlidingTime(string objId, object o, int slidingTime, System.Web.Caching.CacheItemPriority priority, CacheItemRemovedCallback target)
            {
                if (slidingTime > 0 && webCache != null)
                {
                    if (!String.IsNullOrEmpty(objId) && o != null)
                    {
                        webCache.Insert(objId
                            , o
                            , null
                            , DateTime.MaxValue
                            , TimeSpan.FromMilliseconds(slidingTime)
                            , priority
                            , target);
                    }
                }
            }

            public void AddObjectWithDepend(string objId, object o, CacheDependency[] deps, TimeOutBy by, int timeOut, System.Web.Caching.CacheItemPriority priority)
            {
                if (!String.IsNullOrEmpty(objId) && o != null && deps.Length > 0)
                {
                    AggregateCacheDependency aggdep = new AggregateCacheDependency();
                    aggdep.Add(deps);
                    if (by == TimeOutBy.AbsoluteTime)
                    {
                        webCache.Insert(objId, o
                            , aggdep
                            , DateTime.Now.AddMilliseconds(timeOut)
                            , System.Web.Caching.Cache.NoSlidingExpiration
                            , priority
                            , null);

                    }
                    else if (by == TimeOutBy.SlidingTime)
                    {
                        webCache.Insert(objId, o
                            , aggdep
                            , System.Web.Caching.Cache.NoAbsoluteExpiration
                            , TimeSpan.FromMilliseconds(timeOut)
                            , priority
                            , null);
                    }
                    else
                    {
                        webCache.Insert(objId, o
                            , aggdep
                            , System.Web.Caching.Cache.NoAbsoluteExpiration
                            , System.Web.Caching.Cache.NoSlidingExpiration
                            , priority
                            , null);
                    }
                }
            }
            public void AddObjectWithDepend(string objId, object o, CacheDependency[] deps, TimeOutBy by, int timeOut, System.Web.Caching.CacheItemPriority priority, CacheItemRemovedCallback target)
            {
                if (!String.IsNullOrEmpty(objId) && o != null && deps.Length > 0)
                {
                    AggregateCacheDependency aggdep = new AggregateCacheDependency();
                    aggdep.Add(deps);
                    if (by == TimeOutBy.AbsoluteTime)
                    {
                        webCache.Insert(objId, o
                            , aggdep
                            , DateTime.Now.AddMilliseconds(timeOut)
                            , System.Web.Caching.Cache.NoSlidingExpiration
                            , priority
                            , target);

                    }
                    else if (by == TimeOutBy.SlidingTime)
                    {
                        webCache.Insert(objId, o
                            , aggdep
                            , System.Web.Caching.Cache.NoAbsoluteExpiration
                            , TimeSpan.FromMilliseconds(timeOut)
                            , priority
                            , target);
                    }
                    else
                    {
                        webCache.Insert(objId, o
                            , aggdep
                            , System.Web.Caching.Cache.NoAbsoluteExpiration
                            , System.Web.Caching.Cache.NoSlidingExpiration
                            , priority
                            , target);
                    }
                }
            }
            public void RemoveObject(string objId)
            {
                if (!String.IsNullOrEmpty(objId))
                {
                    object o = webCache.Get(objId);
                    if (o != null)
                    {
                        webCache.Remove(objId);
                    }
                }
            }

            public object RetrieveObject(string objId)
            {
                if (!String.IsNullOrEmpty(objId))
                {
                    object o = webCache.Get(objId);
                    if (o != null)
                    {
                        return o;
                    }
                }
                return null;
            }

            public enum TimeOutBy
            {
                SlidingTime, AbsoluteTime, NoTimeOut
            }
        }
    }
}
